﻿/*
 * GdoSqlCommand
 * 
 * initial implementation : 20.9.2008
 *
 * Copyright (c) Adam Sida, asida@centrum.cz.
 * All rights reserved.
 * 
 * for license see Petra.Gis.License.txt
 */
using System;

using System.Collections;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.Data;
using System.Data.Common;
using System.Data.SqlClient;
using Petra.Gis.Geometry;
using Petra.Gis.Geometry.Support;
//using Petra.Gis.ReferenceSystemServices;
using Petra.Gis.DataServices;
using Petra.Gis.DataServices.Metadata;

namespace Petra.Gis.DataServices.GDO.Sqlserver
{
  public partial class GdoSqlCommand : SpatialDbCommand
  {

    //private GdoSqlConnection _conection;
    protected SqlCommand _sqlCmd;
    protected SqlTransaction _trans;
    //private List<string> _gFieldNames;

    // Implement the default constructor here.
    public GdoSqlCommand()
      :base()
    {
      
      _sqlCmd = new SqlCommand();
    }



    // Implement other constructors here.
    public GdoSqlCommand(string cmdText)
      : base(cmdText)
    { }




    public GdoSqlCommand(string cmdText, GdoSqlConnection connection)
      : base(cmdText, connection)
    {
      //this.Connection = connection;

      _sqlCmd.Connection = (SqlConnection)connection.Extensions["SqlConnection"];

      //this.CommandText = cmdText;

      //internal wrapped sql command must get normal SqlConnection
      //it is accessible via extensions ;-)
      //prepareSpatialMetadata();
    }




    public GdoSqlCommand(string cmdText, GdoSqlConnection connection, SqlTransaction txn)
      : this(cmdText, connection)
    {
      _trans = txn;
      //prepareSpatialMetadata();
    }




    //private void prepareCommand()
    //{ 
    //  //select basic gdo metadata
    //  //select all geometry field names

    //  SqlCommand tmpCmd = _sqlCmd.Connection.CreateCommand();
    //  //todo:repair
    //  //tmpCmd.CommandText = GdoSqlCommand.sqlGetGeometryFieldNames; //from resource

    //  SqlDataReader dr = tmpCmd.ExecuteReader();

    //  _gFieldNames = new List<string>();

    //  while (dr.Read())
    //  {
    //    _gFieldNames.Add(dr.GetString(0));
    //  }

    //}





    public override bool DesignTimeVisible
    {
      get { return false; }
      set {  }
    }




    public override string CommandText
    {
      get { return _sqlCmd.CommandText; }
      set 
      {
        // if text not null or empty
        if (value != null && value != "")
        {
          _sqlCmd.CommandText = value;
          //Metadata = getFeatureMetadata();
        }
         
      }
    }





    public override int CommandTimeout
    {
      /*
       * The sample does not support a command time-out. As a result,
       * for the get, zero is returned because zero indicates an indefinite
       * time-out period. For the set, throw an exception.
       */
      get { return _sqlCmd.CommandTimeout; }
      set { _sqlCmd.CommandTimeout = value; }
    }





    public override CommandType CommandType
    {
      get { return _sqlCmd.CommandType; }
      set 
      {
        _sqlCmd.CommandType = value;
        //getSpatialMetadata();
      }
    }





    protected override DbConnection DbConnection
    {
      get { return this.Connection; }
      set { this.Connection = (GdoSqlConnection)value; }
    }





    protected GdoSqlConnection _connection;

    new public GdoSqlConnection Connection
    {
      get { return _connection; }
      set
      {

        /*
         * The connection is associated with the transaction
         * so set the transaction object to return a null reference if the connection 
         * is reset.
         */
        if (_connection != value)
          this.Transaction = null;

        _connection = value;
        _sqlCmd.Connection = (SqlConnection)_connection.Extensions["SqlConnection"];
      }
    }




    ////protected SptlDbParameterCollection _parameters;

    //new public SptlDbParameterCollection Parameters
    //{
    //  get { return (SptlDbParameterCollection)DbParameterCollection; }
    //}




    //protected override DbParameterCollection DbParameterCollection
    //{
    //  get { return _parameters; }
    //}




    /// <summary>
    /// databse data source, reads data using OLEDB
    /// </summary>
    public override FeatureDataSourceTypeEnum FeatureDataSourceType
    {
      get
      {
        return FeatureDataSourceTypeEnum.NetworkAndDatabaseDataSource;
      }
    }



    new public DbTransaction Transaction
    {
      /*
       * Set the transaction. Consider additional steps to ensure that the transaction
       * is compatible with the connection, because the two are usually linked.
       */
      get { return _trans; }
      set { _trans = (SqlTransaction)value; }
    }




    protected override DbTransaction DbTransaction
    {
      /*
       * Set the transaction. Consider additional steps to ensure that the transaction
       * is compatible with the connection, because the two are usually linked.
       */
      get { return this.Transaction; }
      set { this.Transaction = value; }
    }



    public override UpdateRowSource UpdatedRowSource
    {
      get { return _sqlCmd.UpdatedRowSource; }
      set { _sqlCmd.UpdatedRowSource = value; }
    }



    /****
     * IMPLEMENT THE REQUIRED METHODS.
     ****/
    public override void Cancel()
    {
      _sqlCmd.Cancel();
    }





    new public SptlDbParameter CreateParameter()
    {
      return new SptlDbParameter();
    }


    protected override DbParameter CreateDbParameter()
    {
      return this.CreateParameter();
    }





    public override int ExecuteNonQuery()
    {
      /*
       * ExecuteNonQuery is intended for commands that do
       * not return results, instead returning only the number
       * of records affected.
       */

      // validate before run
      validateBeforeRun();

      // Execute the command.
      return _sqlCmd.ExecuteNonQuery();

    }



    new public GdoSqlDataReader ExecuteReader()
    {
      // validate before run, SpatialDbCommand.validateBeforeRun()
      validateBeforeRun();

      //try prepare spatial metadata
      //prepareSpatialMetadata();

      //prepare spatial filter
      if (this.Parameters != null)
        prepareSpatialFilters();

      //object p = _sqlCmd.Parameters[1];

      return getgdosqlDataReader(_sqlCmd.ExecuteReader());
    }




    new public GdoSqlDataReader ExecuteReader(CommandBehavior behavior)
    {
      // validate before run
      validateBeforeRun();

      //try prepare spatial metadata
      //prepareSpatialMetadata();

      //prepare spatial filter
      if (this.Parameters != null)
        prepareSpatialFilters();

      return getgdosqlDataReader(_sqlCmd.ExecuteReader(behavior));
    }




    protected override DbDataReader ExecuteDbDataReader(CommandBehavior behavior)
    {
      return this.ExecuteReader(behavior);
    }




    private GdoSqlDataReader getgdosqlDataReader(SqlDataReader dr)
    {

      GdoSqlDataReader retval = new GdoSqlDataReader(this, dr);
      return retval;
    }




    public override object ExecuteScalar()
    {
      // validate before run
      validateBeforeRun();

      return _sqlCmd.ExecuteScalar();

    }




    //public override void PrepareCoarseSpatialFilterParameters(Dictionary<string, BoundingBox> bounds)
    //{ 
    //  if(bounds == null)
    //    return;

    //  foreach(KeyValuePair<string,BoundingBox> f in bounds)
    //  {
    //    SqlParameter p = new SqlParameter();
    //    p.ParameterName = "@" + f.Key;
    //    this.Parameters.Add(p);
    //  }
    //}





    public override void Prepare()
    {
      // The sample Prepare is a no-op.
    }

    /*public void Dispose()
    {
      this.Dispose(true);
      System.GC.SuppressFinalize(this);
    }
    */




    protected override void Dispose(bool disposing)
    {
      /*
       * Dispose of the object and perform any cleanup.
       */
      //base.Dispose();
    }

  }
}
